﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;

namespace UstavCSharpClient
{
    public partial class MainForm : Form
    {
        const int POINT_RADIUS = 10;
        Boolean miniMap = true;

        UstavClient client = new UstavClient();

        Point destinationPoint;
        Point centerPoint;

        SolidBrush destinationBrush = new SolidBrush(Color.Blue);
        SolidBrush centerBrush = new SolidBrush(Color.Red);

        public MainForm()
        {
            InitializeComponent();

            // Calculate center point of the map
            centerPoint.X = pictureBoxVideo.ClientRectangle.Width / 2;
            centerPoint.Y = pictureBoxVideo.ClientRectangle.Height / 2;
            destinationPoint = centerPoint;
        }

        private void SwitchViewsProperties()
        {
            Size videoBoxSize = pictureBoxVideo.Size;
            Point videoBoxLocation = pictureBoxVideo.Location;
            AnchorStyles videoBoxAnchor = pictureBoxVideo.Anchor;

            pictureBoxVideo.Size = pictureBoxMap.Size;
            pictureBoxVideo.Location = pictureBoxMap.Location;
            pictureBoxVideo.Anchor = pictureBoxMap.Anchor;

            pictureBoxMap.Size = videoBoxSize;
            pictureBoxMap.Location = videoBoxLocation;
            pictureBoxMap.Anchor = videoBoxAnchor;

            miniMap = !miniMap;
        }       
        
        private void LoadImages()
        {
            Image im;
            // Get heading:
           
            pictureBoxVideo.Refresh();
            Size sz = pictureBoxVideo.Size;
            Point pt = pictureBoxVideo.Location;

            /*ruler*/
            int altitude = 0;
            try
            {
                altitude = Convert.ToInt32(textBoxAltitude.Text);
            }
            catch
            {
                altitude = 0;
            }

            float scaleXruler = 1.0F;
            float scaleYruler = 1.0F;
            Bitmap ruler = new Bitmap(UstavCSharpClient.Properties.Resources.ruler);
            im = CropImageVertical(ruler, altitude, 300);
            Graphics gra1 = pictureBoxVideo.CreateGraphics();
            // Draw image center to the center of the bottom of video box
            gra1.DrawImage(im, new Point(pt.X + (int)(sz.Width * 2/3) - (int)(im.Width * scaleXruler),
                pt.Y + (sz.Height - (int)(im.Height * scaleYruler)) / 2));



            /*compas*/
            int heading = 0;
            try
            {
                heading = Convert.ToInt32(textBoxHeading.Text);
            }
            catch
            {
                heading = 0;
            }


            float scaleXcompas = 0.15F;
            float scaleYcompas = 0.15F;
            Bitmap compas = new Bitmap(UstavCSharpClient.Properties.Resources.compass);
            im = RotateImage(compas, heading);
            im = ScaleImage(im, scaleXcompas, scaleYcompas);
                        
            Graphics gra = pictureBoxVideo.CreateGraphics();
            // Draw image center to the center of the bottom of video box
            gra.DrawImage(im, new Point(pt.X + (sz.Width - (int)(im.Width * scaleXcompas)) / 2,
                pt.Y + sz.Height - (int)(im.Height * scaleYcompas) / 2));

        }
        
        public static Image CropImageVertical(Image img, int position, int cropSize)
        {
            //create an empty Bitmap image
            Bitmap bmp = new Bitmap(img.Width, cropSize);

            //turn the Bitmap into a Graphics object
            Graphics gfx = Graphics.FromImage(bmp);

            //now rotate the imageTranslateTransform
            gfx.TranslateTransform(0, -img.Height + position + cropSize);

            //set the InterpolationMode to HighQualityBicubic so to ensure a high
            //quality image once it is transformed to the specified size
            //gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //now draw our new image onto the graphics object
            gfx.DrawImage(img, new Point(0, 0));

            //dispose of our Graphics object
            gfx.Dispose();

            //return the image
            return bmp;
        }
        
        public static Image ScaleImage(Image img, float sx, float sy)
        {
            //create an empty Bitmap image
            Bitmap bmp = new Bitmap(img.Width, img.Height);

            //turn the Bitmap into a Graphics object
            Graphics gfx = Graphics.FromImage(bmp);

            //now scale the image
            gfx.ScaleTransform(sx, sy);

            //set the InterpolationMode to HighQualityBicubic so to ensure a high
            //quality image once it is transformed to the specified size
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //now draw our new image onto the graphics object
            gfx.DrawImage(img, new Point(0, 0));

            //dispose of our Graphics object
            gfx.Dispose();

            //return the image
            return bmp;
        }

        public static Image RotateImage(Image img, float rotationAngle)
        {
            //create an empty Bitmap image
            Bitmap bmp = new Bitmap(img.Width, img.Height);

            //turn the Bitmap into a Graphics object
            Graphics gfx = Graphics.FromImage(bmp);

            //now we set the rotation point to the center of our image
            gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);

            //now rotate the image
            gfx.RotateTransform(rotationAngle);

            gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);

            //set the InterpolationMode to HighQualityBicubic so to ensure a high
            //quality image once it is transformed to the specified size
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //now draw our new image onto the graphics object
            gfx.DrawImage(img, new Point(0, 0));

            //dispose of our Graphics object
            gfx.Dispose();

            //return the image
            return bmp;
        }

        private void AddPoint(Point coordinate)
        {
            destinationPoint = coordinate;
 
            textBoxLatitude.Text = coordinate.X.ToString();
            textBoxLongitude.Text = coordinate.Y.ToString();

        }

        #region Events

        private void buttonGo_Click(object sender, EventArgs e)
        {
             HandleErrorCode(client.Send_GO(Convert.ToSingle(textBoxLatitude.Text), 
                                            Convert.ToSingle(textBoxLongitude.Text),
                                            Convert.ToSingle(textBoxAltitude.Text)));
        }

        private void buttonWait_Click(object sender, EventArgs e)
        {
             HandleErrorCode(client.Send_WAIT(Convert.ToInt32(textBoxWaitTime.Text)));
        }

        private void checkBoxLightFrontLeft_CheckedChanged(object sender, EventArgs e)
        {
            HandleErrorCode(client.Send_LIGHTS(UstavClient.FRONT_LEFT_LIGHT, checkBoxLightFrontLeft.Checked));
        }

        private void checkBoxLightFrontRight_CheckedChanged(object sender, EventArgs e)
        {
            HandleErrorCode(client.Send_LIGHTS(UstavClient.FRONT_RIGHT_LIGHT, checkBoxLightFrontRight.Checked));
        }

        private void checkBoxLightRearLeft_CheckedChanged(object sender, EventArgs e)
        {
            HandleErrorCode(client.Send_LIGHTS(UstavClient.REAR_LEFT_LIGHT, checkBoxLightRearRight.Checked));
        }

        private void checkBoxLightRearRight_CheckedChanged(object sender, EventArgs e)
        {
            HandleErrorCode(client.Send_LIGHTS(UstavClient.REAR_RIGHT_LIGHT));
        }

        private void buttonConnectToServer_Click(object sender, EventArgs e)
        {
            // Get IP segments
            string A = textBoxA.Text;
            string B = textBoxB.Text;
            string C = textBoxC.Text;
            string D = textBoxD.Text;

            // Create IP from segments
            string IP = String.Format("{0}.{1}.{2}.{3}", A, B, C, D);

            // Get port number (currently hardcoded)
            int port = Convert.ToInt32(labelPort.Text);

            // Try to connect to server
            if (client.Connect(IP, port) != 0)
            {
                richTextBoxConnectResult.Text = "ERROR CONNECTING TO THE SERVER";
                buttonOverride.Show();
                return;
            }

            // Show can go on
            panelStart.Hide();
        }

        private void buttonOverride_Click(object sender, EventArgs e)
        {
            // Forcefully continue
            panelStart.Hide();
        }  

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            LoadImages();
        }

        private void buttonSettings_Click(object sender, EventArgs e)
        {
            // Show/Hide settings control
            tabControlSettings.Visible = !tabControlSettings.Visible;

            // Make sure that setting button is visible
            buttonSettings.BringToFront();
        }

        private void pictureBoxVideo_Click(object sender, EventArgs e)
        {

            if (!miniMap)
            {
                SwitchViewsProperties();
                pictureBoxVideo.SendToBack();
            }
        }

        private void pictureBoxVideo_Paint(object sender, PaintEventArgs e)
        {
            /// Declares the Graphics object and sets it to the Graphics object
            //// supplied in the PaintEventArgs.
            Graphics formGraphics = e.Graphics;
            //// Insert code to paint the form here.
        }

        private void pictureBoxMap_Click(object sender, EventArgs e)
        {
            if (miniMap)
            {
                SwitchViewsProperties();
                pictureBoxMap.SendToBack();
            }
        }
        
        private void pictureBoxMap_DoubleClick(object sender, EventArgs e)
        {
            if (!miniMap)
            {
                MouseEventArgs args = e as MouseEventArgs;
                AddPoint(args.Location);
                pictureBoxMap.Invalidate();
            }
        }

        private void pictureBoxMap_Paint(object sender, PaintEventArgs e)
        {
            // Declares the Graphics object and sets it to the Graphics object supplied in the PaintEventArgs.
            Graphics formGraphics = e.Graphics;

            // Insert code to paint the form here.

            // Setup ratio for correct  minimap shapes sizes
            float ratio = miniMap ? pictureBoxMap.Size.Width / (float)pictureBoxVideo.Size.Width : 1f;

            // Draw center point marker circle
            formGraphics.FillEllipse(centerBrush, new Rectangle(
                Convert.ToInt32((centerPoint.X - POINT_RADIUS) * ratio), 
                Convert.ToInt32((centerPoint.Y - POINT_RADIUS) * ratio), 
                Convert.ToInt32(2 * POINT_RADIUS * ratio), 
                Convert.ToInt32(2 * POINT_RADIUS * ratio))); 
                
            if (destinationPoint != centerPoint)
            {                
                // Draw destination point marker circle
                formGraphics.FillEllipse(destinationBrush, new Rectangle(
                        Convert.ToInt32((destinationPoint.X - POINT_RADIUS) * ratio),
                        Convert.ToInt32((destinationPoint.Y - POINT_RADIUS) * ratio),
                        Convert.ToInt32(2 * POINT_RADIUS * ratio),
                        Convert.ToInt32(2 * POINT_RADIUS * ratio)));
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            // Position the settings control (hidden) to top left corner
            tabControlSettings.Location = pictureBoxVideo.Location;

            // Position starting pannel to top left corner
            panelStart.Location = pictureBoxVideo.Location;
            panelStart.BringToFront();

        }

        #endregion Events

        private void HandleErrorCode(int errorCode)
        {
            if (errorCode == UstavClient.CONNECTION_LOST)
            {
                richTextBoxConnectResult.Text = "CONNECTION LOST";
                panelStart.Show();
            }
        }

    }
}
